﻿using FluentScheduler;
using OUS_HUB.Jobs;
using PacoToolKit.Format;
using PacoToolKit.Ini;
using PacoToolKit.Log;
using Protocol.OUSProtocol.Decoder;
using Protocol.OUSProtocol.Encoder;
using Protocol.OUSProtocol.Model;
using SuperSocket.SocketBase;
using SuperSocket.SocketBase.Config;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using TcpServer.ClientServer;
using TcpServer.OUServer;

namespace OUS_HUB
{
    public partial class FormMain : Form
    {
        private static readonly string DIRECTORY = System.IO.Directory.GetCurrentDirectory();
        public readonly static string APPPATH = Application.StartupPath;
        public readonly static string CONFIGFILE = APPPATH + "\\config.ini";
        public readonly static string FIRMWAREPATH = APPPATH + "\\Firmware\\";


        public static Color ColorInfo = Color.DeepSkyBlue;
        public static Color ColorText = Color.White;
        //全局
        public DateTime GLOBAL_START_TIME = DateTime.Now;
        private OUServerProtocolServer SERVER;
        private ClientServer WEBSERVER;
        public int port = 30201;//无配置默认
        public int webport = 9998;//无配置默认
        public int web_timeout = 30;
        public int timeInterval = 300;
        public string intervaltype = "秒";
        public string interface_url = string.Empty;
        public string interface_url1 = string.Empty;
        public string interface_appid = string.Empty;
        public string interface_appsecret = string.Empty;
        public string device_head = string.Empty;
        public int firmware_single_size = 1024;

        public static DebugModel DebugModel = DebugModel.Release;
        public DataTable DeviceListDataTable = new DataTable();
        public List<Ous> OUS_LIST = new List<Ous>();
        public List<WebRequest> clientList = new List<WebRequest>();
        public Firmware Firmware = new Firmware();
        public static bool CAN_UPDATE = false;
        public string SELECTED_ADDR_REVERSE = "";
        public string testbuff = "";
        public static Dictionary<string, uint> AlarmRecord = new Dictionary<string, uint>() { };//设备告警字典

        public FormMain()
        {
            InitializeComponent();
            Init();

        }

        private void Init()
        {
            try
            {
                port = int.Parse(IniHelper.ReadIniContentValue("config", "port", CONFIGFILE));
                webport = int.Parse(IniHelper.ReadIniContentValue("config", "webport", CONFIGFILE));
                web_timeout = int.Parse(IniHelper.ReadIniContentValue("config", "web_timeout", CONFIGFILE));
                this.textBoxPort.Text = port.ToString();



                SERVER = new OUServerProtocolServer();
                var serverConfig = new ServerConfig
                {
                    /*
                    name: 服务器实例的名称;
                    serverType: 服务器实例的类型的完整名称;
                    serverTypeName: 所选用的服务器类型在 serverTypes 节点的名字，配置节点 serverTypes 用于定义所有可用的服务器类型，我们将在后面再做详细介绍;
                    ip: 服务器监听的ip地址。你可以设置具体的地址，也可以设置为下面的值 Any - 所有的IPv4地址 IPv6Any - 所有的IPv6地址
                    port: 服务器监听的端口;
                    listenBacklog: 监听队列的大小;
                    mode: Socket服务器运行的模式, Tcp (默认) 或者 Udp;
                    disabled: 服务器实例是否禁用了;
                    startupOrder: 服务器实例启动顺序, bootstrap 将按照此值的顺序来启动多个服务器实例;
                    sendTimeOut: 发送数据超时时间;
                    sendingQueueSize: 发送队列最大长度, 默认值为5;
                    maxConnectionNumber: 可允许连接的最大连接数;
                    receiveBufferSize: 接收缓冲区大小;
                    sendBufferSize: 发送缓冲区大小;
                    syncSend: 是否启用同步发送模式, 默认值: false;
                    logCommand: 是否记录命令执行的记录;
                    logBasicSessionActivity: 是否记录session的基本活动，如连接和断开;
                    logAllSocketException: 是否记录所有Socket异常和错误;
                    clearIdleSession: true 或 false, 是否定时清空空闲会话，默认值是 false;
                    clearIdleSessionInterval: 清空空闲会话的时间间隔, 默认值是120, 单位为秒;
                    idleSessionTimeOut: 会话空闲超时时间; 当此会话空闲时间超过此值，同时clearIdleSession被配置成true时，此会话将会被关闭; 默认值为300，单位为秒;
                    security: Empty, Tls, Ssl3. Socket服务器所采用的传输层加密协议，默认值为空; 你也可以设置多个值，如 "Tls11,Tls12";
                    maxRequestLength: 最大允许的请求长度，默认值为1024;
                    textEncoding: 文本的默认编码，默认值是 ASCII;
                    defaultCulture: 此服务器实例的默认 thread culture, 只在.Net 4.5中可用而且在隔离级别为 'None' 时无效;
                    disableSessionSnapshot: 是否禁用会话快照, 默认值为 false.
                    sessionSnapshotInterval: 会话快照时间间隔, 默认值是 5, 单位为秒;
                    keepAliveTime: 网络连接正常情况下的keep alive数据的发送间隔, 默认值为 600, 单位为秒;
                    keepAliveInterval: Keep alive失败之后, keep alive探测包的发送间隔，默认值为 60, 单位为秒;
                    certificate: 这各节点用于定义用于此服务器实例的X509Certificate证书的信息
                     */
                    KeepAliveTime = 1200,//20min无活动则发送包检测
                    KeepAliveInterval = 60,//检测到无活动则每1min再次发送检测
                    Port = port,
                    Ip = "Any",
                    MaxConnectionNumber = 10000,//2000
                    Mode = SocketMode.Tcp,
                    Name = "Server",
                    TextEncoding = "UTF-8"
                };
                SERVER.Setup(serverConfig);
                SERVER.NewSessionConnected += SERVER_NewSessionConnected; ;
                SERVER.SessionClosed += SERVER_SessionClosed; ;
                SERVER.NewRequestReceived += SERVER_NewRequestReceived; ;
                SERVER.Start();

                WEBSERVER = new ClientServer();
                var webConfig = new ServerConfig
                {
                    Port = webport,
                    Ip = "Any",
                    MaxConnectionNumber = 10000,//2000
                    Mode = SocketMode.Tcp,
                    Name = "WebServer",
                    TextEncoding = "UTF-8",
                    MaxRequestLength = 100000,
                    ReceiveBufferSize = 100000,
                    SendBufferSize = 100000
                };
                WEBSERVER.Setup(webConfig);
                WEBSERVER.NewSessionConnected += WEBSERVER_NewSessionConnected;
                WEBSERVER.NewRequestReceived += WEBSERVER_NewRequestReceived; ;
                WEBSERVER.SessionClosed += WEBSERVER_SessionClosed; ;
                WEBSERVER.Start();

                this.tabPageDebug.Parent = null;

                //datagridview 初始化
                DeviceListDataTable.Columns.Add("选择", typeof(bool));
                DeviceListDataTable.Columns.Add("设备", typeof(System.String));
                DeviceListDataTable.Columns.Add("通道", typeof(System.String));
                DeviceListDataTable.Columns.Add("版本", typeof(System.String));
                DeviceListDataTable.Columns.Add("状态", typeof(System.String));


                dataGridViewDeviceList.DataSource = DeviceListDataTable;

                dataGridViewDeviceList.Columns[0].Width = 80;
                dataGridViewDeviceList.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;

                dataGridViewDeviceList.Columns[1].ReadOnly = true;
                dataGridViewDeviceList.Columns[1].DefaultCellStyle.ForeColor = Color.Green;
                dataGridViewDeviceList.Columns[1].MinimumWidth = 180;
                dataGridViewDeviceList.Columns[1].SortMode = DataGridViewColumnSortMode.NotSortable;

                dataGridViewDeviceList.Columns[2].ReadOnly = true;
                dataGridViewDeviceList.Columns[2].MinimumWidth = 180;
                dataGridViewDeviceList.Columns[2].SortMode = DataGridViewColumnSortMode.NotSortable;

                dataGridViewDeviceList.Columns[3].ReadOnly = true;
                dataGridViewDeviceList.Columns[3].MinimumWidth = 180;
                dataGridViewDeviceList.Columns[3].SortMode = DataGridViewColumnSortMode.NotSortable;

                dataGridViewDeviceList.Columns[4].ReadOnly = true;
                dataGridViewDeviceList.Columns[4].MinimumWidth = 180;
                dataGridViewDeviceList.Columns[4].SortMode = DataGridViewColumnSortMode.NotSortable;

                //
                dataGridViewDeviceList.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;//宽度铺满全屏
                dataGridViewDeviceList.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;//自动高度
                dataGridViewDeviceList.AllowUserToAddRows = false;


                DataGridViewButtonColumn btn = new DataGridViewButtonColumn();
                btn.Name = "funBtn";
                btn.HeaderText = "";
                btn.Width = 200;
                btn.DefaultCellStyle.NullValue = "读状态";
                dataGridViewDeviceList.Columns.Add(btn);

                DataGridViewButtonColumn btn1 = new DataGridViewButtonColumn();
                btn1.Name = "funBtn1";
                btn1.HeaderText = "";
                btn1.Width = 200;
                btn1.DefaultCellStyle.NullValue = "升级固件";
                dataGridViewDeviceList.Columns.Add(btn1);

                DataGridViewButtonColumn btn2 = new DataGridViewButtonColumn();
                btn2.Name = "funBtn2";
                btn2.HeaderText = "";
                btn2.Width = 200;
                btn2.DefaultCellStyle.NullValue = "参数设置";
                dataGridViewDeviceList.Columns.Add(btn2);


                //测试代码
                /*for (var i = 0; i < 100; i++)
                {
                    DataRow row = DeviceListDataTable.NewRow();
                    row[0] = false;
                    row[1] = i;
                    row[2] = "test";
                    row[3] = "test";
                    DeviceListDataTable.Rows.Add(row);
                }*/

                timeInterval = int.Parse(IniHelper.ReadIniContentValue("config", "timeInterval", CONFIGFILE));
                intervaltype = IniHelper.ReadIniContentValue("config", "intervaltype", CONFIGFILE);
                interface_url = IniHelper.ReadIniContentValue("config", "interface_url", CONFIGFILE);
                interface_url1 = IniHelper.ReadIniContentValue("config", "interface_url1", CONFIGFILE);
                interface_appid = IniHelper.ReadIniContentValue("config", "interface_appid", CONFIGFILE);
                interface_appsecret = IniHelper.ReadIniContentValue("config", "interface_appsecret", CONFIGFILE);
                device_head = IniHelper.ReadIniContentValue("config", "device_head", CONFIGFILE);
                firmware_single_size = int.Parse(IniHelper.ReadIniContentValue("config", "firmware_single_size", CONFIGFILE));

                this.numericUpDownScheduleSpan.Value = timeInterval;
                this.comboBoxScheduleUnit.Text = intervaltype;
                this.textBoxUrl.Text = interface_url;
                this.textBoxUrl1.Text = interface_url1;
                this.textBoxAppid.Text = interface_appid;
                this.textBoxAppsecret.Text = interface_appsecret;

                RestartSchedule("RealTimeJob", new RealTimeJob(this));
                JobManager.AddJob(new AppHeartbeatJob(this), s => s.WithName("AppHeartbeatJob").NonReentrant().ToRunNow().AndEvery(30).Seconds());

                ReadFirmware();
                this.textBoxFirmwareInfo.Text = Firmware.LocalFileName;

            }
            catch (Exception e)
            {
                Logger.Info("Init Error", e);
                MessageBox.Show(e.Message);
            }
            Logger.Info("Init OK.");
        }

        private void WEBSERVER_NewSessionConnected(ClientServerSession session)
        {
            clientList.Add(new WebRequest(session, web_timeout));
            Log("client " + session.RemoteEndPoint.ToString() + " connected.");
        }

        private void WEBSERVER_SessionClosed(ClientServerSession session, SuperSocket.SocketBase.CloseReason value)
        {
            try
            {
                var rep = session.RemoteEndPoint;
                //寻找会话，释放资源
                var match = clientList.Where(x => x.Session.RemoteEndPoint.ToString().Equals(rep.ToString())).ToList();
                if (match.Count() > 0)
                {
                    clientList.Remove(match.First());
                    match.First().Session.Close();
                    Log("client " + session.RemoteEndPoint.ToString() + " disconnected. reason:" + value);
                }
            }
            catch (Exception e)
            {
                Log(e.Message);
                Logger.Info(e.Message + "\r\n" + e.StackTrace);
            }
        }

        private void WEBSERVER_NewRequestReceived(ClientServerSession session, SuperSocket.SocketBase.Protocol.StringRequestInfo requestInfo)
        {
            Log("接受到来自客户端 [" + session.RemoteEndPoint.ToString() + "] 的请求:\n" + requestInfo.Body);
            try
            {
                HandleWebRequest(session, requestInfo.Body);
            }
            catch (Exception e)
            {
                Log(e.Message);
                Logger.Info(e.Message + "\r\n" + e.StackTrace);
            }
        }



        private void SERVER_NewRequestReceived(OUServerProtocolSession session, OUServerProtocolRequestInfo requestInfo)
        {
            LogR(session.RemoteEndPoint.ToString() + "-> " + Space(requestInfo.EntireFrame));
            HandleMsg(session, requestInfo);
        }

        private void SERVER_SessionClosed(OUServerProtocolSession session, SuperSocket.SocketBase.CloseReason value)
        {
            Log(session.RemoteEndPoint.ToString() + "-> closed. reason:" + value);
            //匹配删除
            var matchOUS_LIST = OUS_LIST.Where(x => x.session.RemoteEndPoint.ToString() == session.RemoteEndPoint.ToString());
            if (matchOUS_LIST.Count() > 0)
            {
                OUS_LIST.Remove(matchOUS_LIST.First());
            }
            if (DeviceListDataTable.Rows.Count > 0)
            {
                Invoke(new Action(() =>
                {
                    //删除状态列表
                    var dt = DeviceListDataTable.AsEnumerable();
                    var matchs = (from dt1 in dt//查询
                                 where dt1.Field<string>("通道") == session.RemoteEndPoint.ToString() //条件
                                 select dt1).ToList();
                    if (matchs.Count() > 0)
                    {
                        /*foreach (var datarow in matchs)
                        {
                            Log("设备" + datarow.Field<string>("设备") + "已经离线！");
                            DeviceListDataTable.Rows.Remove(datarow);
                        }*/

                        for (var i = 0; i < matchs.Count; i++)
                        {
                            var datarow = matchs[i];
                            Log("设备" + datarow.Field<string>("设备") + "已经离线！");
                            DeviceListDataTable.Rows.Remove(datarow);
                        }
                    }
                }));
            }
        }

        private void SERVER_NewSessionConnected(OUServerProtocolSession session)
        {
            Log(session.RemoteEndPoint.ToString() + "-> connected.");
        }

        private void HandleMsg(OUServerProtocolSession session, OUServerProtocolRequestInfo info)
        {
            try
            {
                var matchs = (from dt1 in DeviceListDataTable.AsEnumerable()//查询
                             where dt1.Field<string>("设备") == info.DAddrReverse //条件
                             select dt1).ToList();

                #region 登录/读取终端信息/心跳/登出
                if (info.C == "10") //C = 0x10 
                {
                    if (info.AddrDec == 0)//终端主动登录服务器 Addr = 0
                    {
                        string ver = Formater.ASCLLHexBytesToString(Formater.HexStringToBytesKeep(info.Data.Substring(10, 32)));
                        var versionDate = ver.Substring(ver.Length - 8, 8);
                        var year = versionDate.Substring(0, 4);
                        var month = versionDate.Substring(4, 2);
                        var day = versionDate.Substring(6, 2);
                        versionDate = year + "-" + month + "-" + day;
                        var Ous = new Ous { DAddrReverse = info.DAddrReverse, session = session, Version = ver, VersionDate = DateTime.Parse(versionDate), IsUpdating = false, UpdatingPartsIndex = 0 };



                        //remove olds
                        var needDeleteList = new List<Ous>();
                        foreach (Ous ous in OUS_LIST)
                        {
                            if (ous.DAddrReverse == info.DAddrReverse)
                            {
                                needDeleteList.Add(ous);
                            }
                        }
                        foreach (var ous in needDeleteList)
                        {
                            OUS_LIST.Remove(ous);
                        }

                        if (this.IsHandleCreated)
                        {
                            Invoke(new Action(() =>
                            {
                                /*foreach (var datarow in matchs)
                                {
                                    Log("设备" + datarow.Field<string>("设备") + "已经离线！");
                                    DeviceListDataTable.Rows.Remove(datarow);
                                }*/
                                for (var i = 0; i < matchs.Count(); i++)
                                {
                                    var datarow = matchs[i];
                                    Log("设备" + datarow.Field<string>("设备") + "已经离线！");
                                    DeviceListDataTable.Rows.Remove(datarow);
                                }
                            }));
                        }

                        //add mew
                        OUS_LIST.Add(Ous);
                        DataRow row = DeviceListDataTable.NewRow();
                        row[0] = false;
                        row[1] = info.DAddrReverse;
                        row[2] = session.RemoteEndPoint.ToString();
                        row[3] = Ous.Version;
                        row[4] = string.Empty;

                        dataGridViewDeviceList.Invoke(new Action(() => DeviceListDataTable.Rows.Add(row)));

                        string msg = BaseEncoder.CreateAnswerMsg(info.DAddrReverse, info.seqDec, info.C, 0, 1, "00");
                        Write(session, msg);

                        //登陆后自动读取一次状态
                        System.Threading.Thread.Sleep(1000);
                        ReadStatus(info.DAddrReverse);

                    }

                    else if (info.AddrDec == 1)//终端主动发送心跳报文
                    {
                        //心跳
                        string data = string.Empty;
                        string version = string.Empty;
                        if (Firmware.LocalFileName.Split('_').Length > 1)
                        {
                            version = Firmware.LocalFileName.Split('_')[1];
                        }
                        else
                        {
                            version = string.Empty;
                            Log("服务器固件不存在或名称不符合规范.即将使用空版本号");
                        }
                        data = (Formater.StringToASCLLHexStr(version).PadLeft(32, '0'));//写入服务器版本号信息
                        string msg = BaseEncoder.CreateAnswerMsg(info.DAddrReverse, info.seqDec, info.C, 1, 16, data);
                        Write(session, msg);



                        if (info.Data == "1352")
                        {
                            //设备要求更新固件
                            var match_ous = OUS_LIST.Where(x => x.DAddrReverse == info.DAddrReverse);
                            if (match_ous.Count() > 0)
                            {
                                var match = match_ous.First();
                                if (match.IsUpdating)
                                {
                                    Log("设备:" + info.DAddrReverse + "正在升级，忽略设备升级请求");
                                    return;
                                }
                            }

                            Log("开始升级设备:" + info.DAddrReverse + "...");
                            System.Threading.Thread.Sleep(1000);
                            var tem = new OUServerProtocolRequestInfo();
                            tem.DAddrReverse = info.DAddrReverse;
                            tem.seqDec = 0;
                            tem.C = "30";
                            tem.AddrDec = 1;//
                            tem.DLenDec = 40;//
                            string FileName = (Formater.StringToASCLLHexStr(Firmware.LocalFileName).PadLeft(64, '0'));
                            string FileSize = Formater.ReverseHexString(Formater.DECtoHEX(Firmware.LocalFileSize.ToString()).PadLeft(8, '0'));
                            string FileCrc16 = Formater.ReverseHexString(Firmware.LocalCrc16Hex);
                            string TotalPart = Formater.ReverseHexString(Formater.DECtoHEX(Firmware.LocalTotalPart.ToString()).PadLeft(4, '0'));
                            tem.Data = FileName + FileSize + FileCrc16 + TotalPart;

                            msg = BaseEncoder.CreateMsg(tem.DAddrReverse, tem.seqDec, tem.C, tem.AddrDec, tem.DLenDec, tem.Data);
                            Write(session, msg);
                            Log("写入设备:" + tem.DAddrReverse + " 固件信息...");
                        }
                        else
                        {
                            Invoke(new Action(() =>
                            {
                                foreach (var datarow in matchs)
                                {

                                    Log("设备" + info.DAddrReverse + "心跳！");
                                    //todo DeviceListDataTable update
                                    //datarow["版本"] = "心跳";
                                }

                            }));
                        }
                    }

                }
                #endregion
                //告警
                if (info.C == "02")
                {
                    DecodeAlarm(session, info);
                }
                if (info.C == "82")
                {
                    //读状态返回
                    DecodeStatus(info);
                }
                if (info.C == "80")
                {
                    //读参数返回
                    DecodeParam(session, info);
                }
                if (info.C == "81")
                {
                    //写参数返回
                    Invoke(new Action(() =>
                    {
                        Msg("设置成功", Color.DeepSkyBlue, Color.White, 400, 1000);
                    }));
                    var matchClientList = clientList.Where(x => x.dtype == 0 && x.daddr.ToString() == info.DAddrReverse && x.func == "setparams" && x.TimeOut == false);
                    if (matchClientList.Count() > 0)
                    {
                        var matchclient = matchClientList.First();
                        var webResData = new WebResData() { errorcode = 0, resdata = "success" };
                        Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                        matchclient.Session.Close();
                    }
                }
                #region 升级固件相关
                if (info.C == "B0")
                {
                    //
                    if (info.AddrDec == 0)
                    {
                        //读固件返回
                        var remoteFirmware = new RemoteFirmware();
                        remoteFirmware.RemoteFileName = Formater.ASCLLHexBytesToString(Formater.HexStringToBytes(info.Data.Substring(0, 32 * 2)));
                        remoteFirmware.RemoteFileSize = Formater.HEXtoDEC(Formater.ReverseHexString(info.Data.Substring(64, 4 * 2)));
                        remoteFirmware.RemoteFileCrc16 = Formater.ReverseHexString(info.Data.Substring(72, 2 * 2));
                        remoteFirmware.RemoteTotalPart = Formater.HEXtoDEC(Formater.ReverseHexString(info.Data.Substring(76, 2 * 2)));
                        remoteFirmware.RemoteRecievePart = Formater.HEXtoDEC(Formater.ReverseHexString(info.Data.Substring(80, 2 * 2)));
                        Log(PacoToolKit.Json.Serializer.SerializeObject(remoteFirmware));
                        if (remoteFirmware.RemoteFileCrc16 == Firmware.LocalCrc16Hex)
                        {
                            if (remoteFirmware.RemoteRecievePart == remoteFirmware.RemoteTotalPart)
                            {
                                Log("设备固件与本地一致，将覆盖设备固件...");
                            }
                            else
                            {
                                Log("设备固件与本地一致,但不完整,将覆盖设备固件...");
                            }

                        }

                        Log("开始升级设备:" + info.DAddrReverse + "...");
                        var tem = new OUServerProtocolRequestInfo();
                        tem.DAddrReverse = info.DAddrReverse;
                        tem.seqDec = 0;
                        tem.C = "30";
                        tem.AddrDec = 1;//
                        tem.DLenDec = 40;//
                        string FileName = (Formater.StringToASCLLHexStr(Firmware.LocalFileName).PadLeft(64, '0'));
                        string FileSize = Formater.ReverseHexString(Formater.DECtoHEX(Firmware.LocalFileSize.ToString()).PadLeft(8, '0'));
                        string FileCrc16 = Formater.ReverseHexString(Firmware.LocalCrc16Hex);
                        string TotalPart = Formater.ReverseHexString(Formater.DECtoHEX(Firmware.LocalTotalPart.ToString()).PadLeft(4, '0'));
                        tem.Data = FileName + FileSize + FileCrc16 + TotalPart;

                        string msg = BaseEncoder.CreateMsg(tem.DAddrReverse, tem.seqDec, tem.C, tem.AddrDec, tem.DLenDec, tem.Data);
                        Write(session, msg);
                        Log("写入设备:" + tem.DAddrReverse + " 固件信息...");
                    }
                    if (info.AddrDec == 1)
                    {
                        //写文件信息 返回
                        if (info.Data == "00" && info.DLenDec == 1)
                        {
                            //写入第一帧
                            Log("传输:" + info.DAddrReverse + " 固件信息...");
                            var match_ous = OUS_LIST.Where(x => x.DAddrReverse == info.DAddrReverse);
                            if (match_ous.Count() > 0 && matchs.Count() > 0)
                            {
                                var match = match_ous.First();
                                match.IsUpdating = true;
                                match.UpdatingPartsIndex = 0;

                                var match_row = matchs.First();
                                match_row[4] = "0%";

                                var tem = new OUServerProtocolRequestInfo();
                                tem.DAddrReverse = info.DAddrReverse;
                                tem.seqDec = 0;
                                tem.C = "30";
                                tem.AddrDec = 2;//



                                string pkgNumHex = Formater.ReverseHexString(Formater.DECtoHEX(0.ToString()).PadLeft(4, '0'));
                                byte[] pkgdata;
                                if (match.UpdatingPartsIndex == (Firmware.LocalTotalPart - 1))
                                {
                                    //最后一帧
                                    pkgdata = Firmware.Content.Skip(firmware_single_size * match.UpdatingPartsIndex).ToArray();
                                }
                                else
                                {
                                    pkgdata = Firmware.Content.Skip(firmware_single_size * match.UpdatingPartsIndex).Take(firmware_single_size).ToArray();
                                }

                                tem.DLenDec = pkgdata.Length + 2 + 2;//
                                string pkgdataHex = Formater.BytesToHexStr(pkgdata);
                                string pkgcrc16Hex = (Formater.BytesToHexStr(Formater.crc16(pkgdata, pkgdata.Length)));
                                tem.Data = pkgNumHex + pkgdataHex + pkgcrc16Hex;
                                string msg = BaseEncoder.CreateMsg(tem.DAddrReverse, tem.seqDec, tem.C, tem.AddrDec, tem.DLenDec, tem.Data);
                                Write(session, msg);
                                Log("写入设备:" + tem.DAddrReverse + " 固件,第" + match.UpdatingPartsIndex.ToString() + "帧");

                            }
                        }
                    }
                    else if (info.AddrDec == 2)
                    {
                        var match_ous = OUS_LIST.Where(x => x.DAddrReverse == info.DAddrReverse);
                        if (match_ous.Count() > 0 && matchs.Count() > 0)
                        {
                            var match = match_ous.First();
                            //传文件返回
                            if (info.Data == "00")//正确应答
                            {
                                if (match.UpdatingPartsIndex == (Firmware.LocalTotalPart - 1))
                                {
                                    //是最后一帧的应答，结束上传
                                    match.IsUpdating = false;
                                    match.UpdatingPartsIndex = 0;
                                    var match_row = matchs.First();
                                    match_row[4] = "100%";
                                    Log("写入设备:" + info.DAddrReverse + " 固件完成");
                                }
                                else
                                {
                                    //未结束，继续下一帧
                                    match.UpdatingPartsIndex++;
                                    match.IsUpdating = true;
                                    var match_row = matchs.First();
                                    match_row[4] = (Math.Round((double)match.UpdatingPartsIndex / Firmware.LocalTotalPart, 4) * 100).ToString() + "%";


                                    var tem = new OUServerProtocolRequestInfo();
                                    tem.DAddrReverse = info.DAddrReverse;
                                    tem.seqDec = match.UpdatingPartsIndex;
                                    tem.C = "30";
                                    tem.AddrDec = 2;//



                                    string pkgNumHex = Formater.ReverseHexString(Formater.DECtoHEX(match.UpdatingPartsIndex.ToString()).PadLeft(4, '0'));
                                    byte[] pkgdata;
                                    if (match.UpdatingPartsIndex == (Firmware.LocalTotalPart - 1))
                                    {
                                        //最后一帧
                                        pkgdata = Firmware.Content.Skip(firmware_single_size * match.UpdatingPartsIndex).ToArray();
                                    }
                                    else
                                    {
                                        pkgdata = Firmware.Content.Skip(firmware_single_size * match.UpdatingPartsIndex).Take(firmware_single_size).ToArray();
                                    }

                                    tem.DLenDec = pkgdata.Length + 2 + 2;//
                                    string pkgdataHex = Formater.BytesToHexStr(pkgdata);
                                    string pkgcrc16Hex = (Formater.BytesToHexStr(Formater.crc16(pkgdata, pkgdata.Length)));
                                    tem.Data = pkgNumHex + pkgdataHex + pkgcrc16Hex;
                                    string msg = BaseEncoder.CreateMsg(tem.DAddrReverse, tem.seqDec, tem.C, tem.AddrDec, tem.DLenDec, tem.Data);
                                    Write(session, msg);
                                    Log("写入设备:" + tem.DAddrReverse + " 固件,第" + match.UpdatingPartsIndex.ToString() + "帧");
                                }
                            }
                            else
                            {
                                //错误应答,结束流程
                                match.IsUpdating = false;
                                match.UpdatingPartsIndex = 0;
                                var match_row = matchs.First();

                                if (info.Data == "01")
                                {
                                    match_row[4] = "包校验错误";
                                }
                                else if (info.Data == "02")
                                {
                                    match_row[4] = "之前数据包未有接收完成";
                                }
                                else
                                {
                                    match_row[4] = "其他错误";
                                }
                                Log("写入设备:" + match.DAddrReverse + " 固件,第" + match.UpdatingPartsIndex.ToString() + "帧，返回" + match_row[4]);
                            }
                        }

                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                Invoke(new Action(() =>
                {
                    Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                    Log(ex.Message + " " + ex.StackTrace);
                }));
            }
        }

        private void HandleWebRequest(ClientServerSession session, string msg)
        {
            var matchClientList = clientList.Where(x => x.Session.RemoteEndPoint.ToString().Equals(session.RemoteEndPoint.ToString()));
            if (matchClientList.Count() > 0)
            {
                foreach (var matchclient in matchClientList)
                {
                    if (matchclient.TimeOut)
                    {
                        break;//超时，不处理，丢弃
                    }
                    else
                    {
                        if (matchclient.Session.Connected)
                        {
                            var webRequestData = new WebRequestData();
                            var webResData = new WebResData() { errorcode = 2, resdata = "" };

                            try
                            {
                                webRequestData = PacoToolKit.Json.Deserializer.DeserializeObject<WebRequestData>(msg);
                                matchclient.dtype = webRequestData.data.dtype;
                                matchclient.daddr = webRequestData.data.daddr;
                                matchclient.func = webRequestData.func;
                            }
                            catch (Exception e)
                            {
                                webResData.errorcode = 2;
                                webResData.resdata = "非法请求";
                                Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                                matchclient.Session.Close();
                                return;
                            }
                            string sign = GetSign(webRequestData.nonce, webRequestData.timestamp, interface_appsecret, string.Empty);//data 不计算

                            if (webRequestData.appid != interface_appid)
                            {
                                webResData.errorcode = 1;
                                Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                                matchclient.Session.Close();
                            }
                            //else if (webRequestData.sign != GetSign(webRequestData.nonce, webRequestData.timestamp, interface_appsecret, PacoToolKit.Json.Serializer.SerializeObject(webRequestData.data)))
                            else if (webRequestData.sign.ToUpper() != sign.ToUpper())
                            {
                                Log(string.Format("本地sign:{0},请求sign:{1},校验失败", sign, webRequestData.sign));
                                webResData.errorcode = 1;
                                webResData.resdata = "授权失败";
                                Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                                matchclient.Session.Close();
                            }
                            else
                            {
                                //auth通过,发送
                                if (webRequestData.data.dtype != 0)
                                {
                                    webResData.errorcode = 2;
                                    webResData.resdata = "设备类型错误";
                                    Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                                    matchclient.Session.Close();
                                }
                                else
                                {
                                    var Ous = OUS_LIST.Where(x => x.DAddrReverse == webRequestData.data.daddr.ToString());
                                    if (Ous.Count() == 0)
                                    {
                                        webResData.errorcode = 2;
                                        webResData.resdata = "设备离线";
                                        Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                                        matchclient.Session.Close();
                                    }
                                    else
                                    {
                                        if (webRequestData.func == "readparams")
                                        {
                                            var info = new OUServerProtocolRequestInfo();
                                            info.DAddrReverse = webRequestData.data.daddr.ToString();
                                            info.seqDec = 1;
                                            info.C = "00";
                                            info.AddrDec = 0;//从第0个字节开始读
                                            info.DLenDec = System.Runtime.InteropServices.Marshal.SizeOf(new SParams());//读取666个字节
                                            info.Data = string.Empty;

                                            string str = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                                            Write(Ous.First().session, str);
                                            //this.statusStrip1.Items[0].Text = "读取...";
                                            var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                                         where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                                         select dt1;
                                            if (matchs.Count() > 0)
                                            {
                                                var match = matchs.First();
                                                match[4] = "读取参数...";

                                            }
                                        }
                                        else if (webRequestData.func == "setparams")
                                        {
                                            //设置参数，先读取参数，然后填充接口设置，再下发
                                            Ous.First().SpecialFlag = "setparams";
                                            Params interfaceParams = PacoToolKit.Json.Deserializer.DeserializeObject<Params>(webRequestData.data.content.ToString());
                                            Ous.First().InterfaceParams = interfaceParams;
                                            var info = new OUServerProtocolRequestInfo();
                                            info.DAddrReverse = webRequestData.data.daddr.ToString();
                                            info.seqDec = 1;
                                            info.C = "00";
                                            info.AddrDec = 0;//从第0个字节开始读
                                            info.DLenDec = System.Runtime.InteropServices.Marshal.SizeOf(new SParams());//读取666个字节
                                            info.Data = string.Empty;

                                            string str = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                                            Write(Ous.First().session, str);
                                            //this.statusStrip1.Items[0].Text = "读取...";
                                            var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                                         where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                                         select dt1;
                                            if (matchs.Count() > 0)
                                            {
                                                var match = matchs.First();
                                                match[4] = "读取参数...";

                                            }
                                        }
                                    }
                                }
                            }


                        }
                    }
                }
            }
        }


        public string PostWebRequest(string postUrl, string paramData, string contentType = "application/x-www-form-urlencoded")
        {
            string ret = string.Empty;
            try
            {
                if (!postUrl.StartsWith("http://"))
                    return "";

                byte[] byteArray = Encoding.UTF8.GetBytes(paramData); //转化
                HttpWebRequest webReq = (HttpWebRequest)System.Net.WebRequest.Create(new Uri(postUrl));
                webReq.Method = "POST";
                webReq.ContentType = contentType;

                webReq.ContentLength = byteArray.Length;
                Stream newStream = webReq.GetRequestStream();
                newStream.Write(byteArray, 0, byteArray.Length);//写入参数
                newStream.Close();
                HttpWebResponse response = (HttpWebResponse)webReq.GetResponse();
                StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
                ret = sr.ReadToEnd();
                sr.Close();
                response.Close();
                newStream.Close();
            }
            catch (Exception ex)
            {
                Invoke(new Action(() =>
                {
                    Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                    Log(ex.Message + " " + ex.StackTrace);
                }));
            }
            return ret;
        }
        private void DecodeStatus(OUServerProtocolRequestInfo info)
        {
            try
            {
                Log(info.Data);
                SStatus _status = (SStatus)PacoToolKit.Memory.Common.BytesToStruct(PacoToolKit.Format.Formater.HexStringToBytesKeep(info.Data), typeof(SStatus), Marshal.SizeOf(typeof(SStatus)));
                var status = BaseDecoder.FomartStatus(_status);

                string json = PacoToolKit.Json.Serializer.SerializeObject(status);
                Log(json);
                

                string url = textBoxUrl.Text;
                string appid = textBoxAppid.Text;
                string nonce = new Random().Next(1, 9999).ToString();
                string timestamp = Formater.DateTimeToStamp(DateTime.Now).ToString();

                string body = string.Empty;
                //"1550460416|0020F36A4686H1R1|Temp1|Temp1|23.5\n1550460416|0020F36A4686H1R1|Hum1|Hum1|80"
                //组合报文
                //JIC19-E00000100
                string device_id = device_head + Formater.AdjustLengthHead(info.DAddrReverse, 8);

                //记录该连接的QCCID信息
                var Ous = OUS_LIST.Where(x => x.DAddrReverse == info.DAddrReverse).ToList();
                if (Ous.Count >= 0)
                {
                    var item = Ous.First();
                    //如果早期版本，不解析
                    if (DateTime.Compare(item.VersionDate, new DateTime(2019, 12, 19)) >= 0)
                    {
                        item.QCCID = status.QCCID;
                        Log("QCCID:" + item.QCCID);
                        item.NH3CO2 = status.NH3CO2;
                        Log("NH3CO2:" + item.NH3CO2);
                        if (status.NH3CO2 == "1")
                        {
                            //co2
                            if (status.co2_r != "-")
                                body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "co2", "co2", status.co2_r);
                        }
                        else
                        {
                            if (status.nh3_r != "-")
                                body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "nh3", "nh3", status.nh3_r);
                        }

                        Log(string.Format("{0} 昨日水读数:{1}", info.DAddrReverse, status.wYestoday));
                        Log(string.Format("{0} 今日水读数:{1}", info.DAddrReverse, status.wToday));
                        var _wUse = decimal.Parse(status.wToday) - decimal.Parse(status.wYestoday);
                        var wUse = _wUse >= 0 ? _wUse.ToString("#0.####") : "0";
                        Log(string.Format("{0} 用水量:{1}", info.DAddrReverse, wUse));
                        body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "water", "water", wUse);

                        Log(string.Format("{0} 昨日电读数:{1}", info.DAddrReverse, status.eYestoday));
                        Log(string.Format("{0} 今日电读数:{1}", info.DAddrReverse, status.eToday));
                        var _eUse = decimal.Parse(status.eToday) - decimal.Parse(status.eYestoday);
                        var eUse = _wUse >= 0 ? _eUse.ToString("#0.#") : "0";
                        Log(string.Format("{0} 用电量:{1}", info.DAddrReverse, eUse));
                        body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "power", "power", eUse);

                    }
                    else
                    {
                        item.QCCID = string.Empty;
                        Log("QCCID:无");
                        item.NH3CO2 = string.Empty;
                        Log("NH3CO2:无");
                        Log("无水电状态");
                        if (status.co2_r != "-")
                            body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "co2", "co2", status.co2_r);
                        if (status.nh3_r != "-")
                            body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "nh3", "nh3", status.nh3_r);
                    }
                }

                if (status.temp_r_List[0] != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "temp1", "temp", status.temp_r_List[0]);
                if (status.temp_r_List[1] != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "temp2", "temp", status.temp_r_List[1]);
                if (status.temp_r_List[2] != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "temp3", "temp", status.temp_r_List[2]);
                if (status.humi_r != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "humi1", "humi", status.humi_r);


                if (status.posDoor != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "posdoor", "posdoor", status.posDoor);
                if (status.posFan != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}\n", timestamp, device_id, "posfan", "posfan", status.posFan);
                if (status.wind_r != "-")
                    body += string.Format("{0}|{1}|{2}|{3}|{4}", timestamp, device_id, "wind", "wind", status.wind_r);

                

                Log(body);
                string sign = GetSign(nonce, timestamp, interface_appsecret, body);
                string posturl = string.Format("{0}?appid={1}&sign={2}&nonce={3}&timestamp={4}", url, appid, sign, nonce, timestamp);
                ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
                {
                    string res = PostWebRequest(posturl, body);
                    var interface_res = PacoToolKit.Json.Deserializer.DeserializeObject<InterfaceRes>(res);
                    Invoke(new Action(() =>
                    {
                        Log(res);
                        var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                     where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                     select dt1;
                        if (interface_res.ErrorCode == 0)
                        {
                            Log(info.DAddrReverse + "发送接口成功");
                            if (matchs.Count() > 0)
                            {
                                var match_row = matchs.First();
                                match_row[4] = "发送接口成功";
                            }
                        }
                        else
                        {
                            Log(info.DAddrReverse + "发送接口失败：" + interface_res.ErrorMessage);
                            if (matchs.Count() > 0)
                            {
                                var match_row = matchs.First();
                                match_row[4] = "发送接口失败：" + interface_res.ErrorMessage;
                            }
                        }
                    }));
                }));

                /*Invoke(new Action(() =>
                {
                    Msg("读取完成", ColorInfo, ColorText, 400, 1000);
                }));*/
            }
            catch (Exception e)
            {
                throw e;
            }
        }
        private void DecodeAlarm(OUServerProtocolSession session, OUServerProtocolRequestInfo info)
        {
            try
            {
                //回复报文
                string msg = BaseEncoder.CreateAnswerMsg(info.DAddrReverse, info.seqDec, info.C, 0, 1, "00");
                Write(session, msg);
                Log(string.Format("收到设备{0} 上报告警", info.DAddrReverse));
                Log(info.Data);
                SStatus _status = (SStatus)PacoToolKit.Memory.Common.BytesToStruct(PacoToolKit.Format.Formater.HexStringToBytesKeep(info.Data), typeof(SStatus), 60);
                var status = BaseDecoder.FomartStatus(_status);
                string json = PacoToolKit.Json.Serializer.SerializeObject(status);
                Log(json);
                //组合报文
                //JIC19-E00000100
                string device_id = device_head + Formater.AdjustLengthHead(info.DAddrReverse, 8);

                List<CAlarm> list = new List<CAlarm>();
                //alarmState解析
                if (AlarmRecord.ContainsKey(info.DAddrReverse))
                {
                    var _old = AlarmRecord[info.DAddrReverse];
                    var _new = _status.alarmState;
                    AlarmRecord[info.DAddrReverse] = _new;//更新字典
                    for (var i = 0; i < 18; i++)
                    {
                        if (GetBitByOffset(_new, i) == 1 && GetBitByOffset(_old, i) == 0)
                        {
                            //告警发生
                            var alarmStr = Alarm.AlarmMap[i];
                            var alarmItem = new CAlarm()
                            {
                                WarningID = System.Guid.NewGuid().ToString(),
                                DeviceMac = device_id,
                                WarnCategory = "1-" + i.ToString(),
                                Remark = alarmStr,
                                WarnTime = Formater.DateTimeToStamp(DateTime.Now).ToString()
                            };
                            list.Add(alarmItem);
                            Log("告警发生: " + PacoToolKit.Json.Serializer.SerializeObject(alarmItem));
                        }
                        else if (GetBitByOffset(_new, i) == 0 && GetBitByOffset(_old, i) == 1)
                        {
                            //告警取消
                            var alarmStr = Alarm.AlarmMap[i];
                            var alarmItem = new CAlarm()
                            {
                                WarningID = System.Guid.NewGuid().ToString(),
                                DeviceMac = device_id,
                                WarnCategory = "0-" + i.ToString(),
                                Remark = alarmStr,
                                WarnTime = Formater.DateTimeToStamp(DateTime.Now).ToString()
                            };
                            list.Add(alarmItem);
                            Log("告警取消: " + PacoToolKit.Json.Serializer.SerializeObject(alarmItem));
                        }
                    }
                }
                else
                {
                    var _new = _status.alarmState;
                    AlarmRecord.Add(info.DAddrReverse, _new);
                    for (var i = 0; i < 18; i++)
                    {
                        if (GetBitByOffset(_new, i) == 1)
                        {
                            //告警发生
                            var alarmStr = Alarm.AlarmMap[i];
                            var alarmItem = new CAlarm()
                            {
                                WarningID = System.Guid.NewGuid().ToString(),
                                DeviceMac = device_id,
                                WarnCategory = "1-" + i.ToString(),
                                Remark = alarmStr,
                                WarnTime = Formater.DateTimeToStamp(DateTime.Now).ToString()
                            };
                            list.Add(alarmItem);
                            Log("告警发生: " + PacoToolKit.Json.Serializer.SerializeObject(alarmItem));
                        }
                    }
                }

                //发送到接口
                foreach (var item in list)
                {
                    string url = textBoxUrl1.Text;
                    string appid = textBoxAppid.Text;
                    string nonce = new Random().Next(1, 9999).ToString();
                    string timestamp = Formater.DateTimeToStamp(DateTime.Now).ToString();

                    string body = string.Empty;
                    body = PacoToolKit.Json.Serializer.SerializeObject(item);




                    string sign = GetSign(nonce, timestamp, interface_appsecret, body);
                    string posturl = string.Format("{0}?appid={1}&sign={2}&nonce={3}&timestamp={4}", url, appid, sign, nonce, timestamp);
                    ThreadPool.QueueUserWorkItem(new WaitCallback(o =>
                    {
                        string res = PostWebRequest(posturl, body, "application/json");
                        var interface_res = PacoToolKit.Json.Deserializer.DeserializeObject<InterfaceRes>(res);
                        Invoke(new Action(() =>
                        {
                            Log(res);
                            var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                         where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                         select dt1;
                            if (interface_res.ErrorCode == 0)
                            {
                                Log(info.DAddrReverse + "发送接口成功");
                                if (matchs.Count() > 0)
                                {
                                    var match_row = matchs.First();
                                    match_row[4] = "发送接口成功";
                                }
                            }
                            else
                            {
                                Log(info.DAddrReverse + "发送接口失败：" + interface_res.ErrorMessage);
                                if (matchs.Count() > 0)
                                {
                                    var match_row = matchs.First();
                                    match_row[4] = "发送接口失败：" + interface_res.ErrorMessage;
                                }
                            }
                        }));
                    }));
                }



            }
            catch (Exception e)
            {
                throw e;
            }
        }

        /// <summary>
        /// 签名算法
        /// </summary>
        /// <param name="nonce"></param>
        /// <param name="timestamp"></param>
        /// <param name="appsecret"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        private string GetSign(string nonce, string timestamp, string appsecret, string body)
        {
            string str = nonce + timestamp + body + appsecret;
            //Log("calc:" + str);
            string md5 = PacoToolKit.Security.Common.GetMD5WithString(str);
            //Log("sign:" + md5);
            return md5;
        }

        private void DecodeParam(OUServerProtocolSession session, OUServerProtocolRequestInfo info)
        {
            try
            {
                //Params _params = BaseDecoder.DecodeParams(info.Data);
                SParams _sparams = (SParams)PacoToolKit.Memory.Common.BytesToStruct(PacoToolKit.Format.Formater.HexStringToBytesKeep(info.Data), typeof(SParams), System.Runtime.InteropServices.Marshal.SizeOf(new SParams()));

                string paramsStr = PacoToolKit.Json.Serializer.SerializeObject(_sparams);
                var matchClientList = clientList.Where(x => x.dtype == 0 && x.daddr.ToString() == info.DAddrReverse && x.func == "readparams" && x.TimeOut == false);
                if (matchClientList.Count() > 0)
                {
                    var matchclient = matchClientList.First();
                    var webResParams = new WebResParams();
                    webResParams.dtype = matchclient.dtype;
                    webResParams.daddr = matchclient.daddr;
                    Params _params = BaseDecoder.DecodeParams(_sparams);
                    webResParams.content = _params;
                    var webResData = new WebResData() { errorcode = 0, resdata = (webResParams) };
                    Write2Web(matchclient.Session, PacoToolKit.Json.Serializer.SerializeObject(webResData));
                    matchclient.Session.Close();
                }

                Log(paramsStr);
                Invoke(new Action(() =>
                {
                    Msg("读取完成", ColorInfo, ColorText, 400, 1000);



                    var controls = this.tabPage温度.Controls;
                    #region 温度曲线
                    for (int i = 0; i < _sparams.tempFig_Day.Length; i++)
                    {
                        var name = "tempFig_Day" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_Day[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.tempFig_Target_Day.Length; i++)
                    {
                        var name = "tempFig_Target_Day" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_Target_Day[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.tempFig_Target_Night.Length; i++)
                    {
                        var name = "tempFig_Target_Night" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_Target_Night[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.tempFig_dTempMax.Length; i++)
                    {
                        var name = "tempFig_dTempMax" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_dTempMax[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.tempFig_WindMin.Length; i++)
                    {
                        var name = "tempFig_WindMin" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_WindMin[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.tempFig_WindMax.Length; i++)
                    {
                        var name = "tempFig_WindMax" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.tempFig_WindMax[i].ToString();
                            }
                        }
                    }

                    #endregion

                    controls = this.tabPage制冷.Controls;
                    #region 制冷--曲线
                    for (int i = 0; i < _sparams.cool_Day.Length; i++)
                    {
                        var name = "cool_Day" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_Day[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_STime.Length; i++)
                    {
                        var name = "cool_STime" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_STime[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_ETime.Length; i++)
                    {
                        var name = "cool_ETime" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_ETime[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_STemp.Length; i++)
                    {
                        var name = "cool_STemp" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_STemp[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_ETemp.Length; i++)
                    {
                        var name = "cool_ETemp" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_ETemp[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_EHumi.Length; i++)
                    {
                        var name = "cool_EHumi" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_EHumi[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_On.Length; i++)
                    {
                        var name = "cool_On" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_On[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.cool_Off.Length; i++)
                    {
                        var name = "cool_Off" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cool_Off[i].ToString();
                            }
                        }
                    }
                    #endregion

                    controls = this.tabPage加热.Controls;
                    #region 加热
                    for (int i = 0; i < _sparams.heat_Day.Length; i++)
                    {
                        var name = "heat_Day" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_Day[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_STime.Length; i++)
                    {
                        var name = "heat_STime" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_STime[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_ETime.Length; i++)
                    {
                        var name = "heat_ETime" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_ETime[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_STemp.Length; i++)
                    {
                        var name = "heat_STemp" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_STemp[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_ETemp.Length; i++)
                    {
                        var name = "heat_ETemp" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_ETemp[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_On.Length; i++)
                    {
                        var name = "heat_On" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_On[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_Off.Length; i++)
                    {
                        var name = "heat_Off" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_Off[i].ToString();
                            }
                        }
                    }

                    for (int i = 0; i < _sparams.heat_Percent.Length; i++)
                    {
                        var name = "heat_Percent" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.heat_Percent[i].ToString();
                            }
                        }
                    }
                    #endregion

                    controls = this.tabPage定时输出.Controls;
                    #region 定时输出
                    for (int i = 0; i < _sparams.timer_On.Length; i++)
                    {
                        var name = "timer_On" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.timer_On[i].ToString();
                            }
                        }
                    }
                    for (int i = 0; i < _sparams.timer_Off.Length; i++)
                    {
                        var name = "timer_Off" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.timer_Off[i].ToString();
                            }
                        }
                    }
                    #endregion

                    controls = this.tabPage校准.Controls;
                    #region 校准

                    for (int i = 0; i < _sparams.cal_dTemp.Length; i++)
                    {
                        var name = "cal_dTemp" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cal_dTemp[i].ToString();
                            }
                        }
                    }
                    for (int i = 0; i < _sparams.cal_dHumi.Length; i++)
                    {
                        var name = "cal_dHumi" + (i + 1).ToString() + "_r";
                        foreach (Control c in controls)
                        {
                            if (c.Name == name)
                            {
                                (c as TextBox).Text = _sparams.cal_dHumi[i].ToString();
                            }
                        }
                    }
                    cal_dNH3_r.Text = _sparams.cal_dNH3.ToString();
                    cal_dCO2_r.Text = _sparams.cal_dCO2.ToString();
                    cal_Wind_r.Text = _sparams.cal_Wind.ToString();
                    cal_Pulse_r.Text = _sparams.cal_Pulse.ToString();
                    #endregion

                    #region 数量统计
                    mh_Day_r.Text = _sparams.mh_Day.ToString();
                    mh_PigNum_r.Text = _sparams.mh_PigNum.ToString();
                    mh_PerWind_r.Text = _sparams.mh_PerWind.ToString();
                    sys_NH3CO2_r.SelectedIndex = (_sparams.sys_NH3CO2);
                    addr_Wmeter_r.Text = _sparams.addr_Wmeter.ToString();
                    addr_Emeter_r.Text = _sparams.addr_Emeter.ToString();
                    #endregion

                    #region 模式控制
                    sys_RunMode_r.SelectedIndex = (_sparams.sys_RunMode);
                    sys_TempMode_r.SelectedIndex = (_sparams.sys_TempMode);
                    sys_WindMode_r.SelectedIndex = (_sparams.sys_WindMode);
                    sys_DoorMode_r.SelectedIndex = (_sparams.sys_DoorMode);
                    #endregion

                    #region 系统变量
                    sys_FanMin_r.Text = _sparams.sys_FanMin.ToString();
                    sys_DoorMin_r.Text = _sparams.sys_DoorMin.ToString();
                    sys_WindStep_r.Text = _sparams.sys_WindStep.ToString();
                    sys_DoorStep_r.Text = _sparams.sys_DoorStep.ToString();
                    sys_WindTime_r.Text = _sparams.sys_WindTime.ToString();
                    sys_HumiAdd_r.Text = _sparams.sys_HumiAdd.ToString();
                    sys_HumiHigh_r.Text = _sparams.sys_HumiHigh.ToString();
                    sys_Humi_Delay_r.Text = _sparams.sys_Humi_Delay.ToString();
                    sys_NH3Add_r.Text = _sparams.sys_NH3Add.ToString();
                    sys_NH3High_r.Text = _sparams.sys_NH3High.ToString();
                    sys_NH3_Delay_r.Text = _sparams.sys_NH3_Delay.ToString();
                    sys_CO2Add_r.Text = _sparams.sys_CO2Add.ToString();
                    sys_CO2High_r.Text = _sparams.sys_CO2High.ToString();
                    sys_CO2_Delay_r.Text = _sparams.sys_CO2_Delay.ToString();
                    sys_DayStart_r.Text = _sparams.sys_DayStart.ToString();
                    sys_DayEnd_r.Text = _sparams.sys_DayEnd.ToString();
                    #endregion

                    #region 报警参数
                    alarm_DoorTO_r.Text = _sparams.alarm_DoorTO.ToString();
                    alarm_TempMax_r.Text = _sparams.alarm_TempMax.ToString();
                    alarm_TempMin_r.Text = _sparams.alarm_TempMin.ToString();
                    alarm_TempDMax_r.Text = _sparams.alarm_TempDMax.ToString();
                    alarm_TempDMin_r.Text = _sparams.alarm_TempDMin.ToString();
                    alarm_HumiMax_r.Text = _sparams.alarm_HumiMax.ToString();
                    alarm_HumiMin_r.Text = _sparams.alarm_HumiMin.ToString();
                    alarm_CO2Max_r.Text = _sparams.alarm_CO2Max.ToString();
                    alarm_NH3Max_r.Text = _sparams.alarm_NH3Max.ToString();
                    alarm_WindMin_r.Text = _sparams.alarm_WindMin.ToString();
                    alarm_TempSensor1_r.SelectedIndex = (_sparams.alarm_TempSensor[0]);
                    alarm_TempSensor2_r.SelectedIndex = (_sparams.alarm_TempSensor[1]);
                    alarm_TempSensor3_r.SelectedIndex = (_sparams.alarm_TempSensor[2]);
                    alarm_HumiSensor1_r.SelectedIndex = (_sparams.alarm_HumiSensor[0]);
                    alarm_NH3Sensor_r.SelectedIndex = (_sparams.alarm_NH3Sensor);
                    alarm_CO2Sensor_r.SelectedIndex = (_sparams.alarm_CO2Sensor);
                    alarm_LostPower_r.SelectedIndex = (_sparams.alarm_LostPower);
                    sys_fixMaxWind_r.Text = _sparams.sys_fixMaxWind.ToString();
                    #endregion

                    #region 通讯设置
                    this.addr_r.Text = _sparams.addr.ToString();
                    this.serverPort_r.Text = _sparams.serverPort.ToString();

                    this.serverIP_r.Text = string.Join(".", _sparams.serverIP);
                    this.localIP_r.Text = string.Join(".", _sparams.localIP);
                    this.gateway_r.Text = string.Join(".", _sparams.gateway);
                    this.netmask_r.Text = string.Join(".", _sparams.netmask);
                    this.comType_r.SelectedIndex = (_sparams.comType);
                    #endregion

                }));

                //
                var matchOus = OUS_LIST.Where(x => x.DAddrReverse == info.DAddrReverse && x.SpecialFlag == "setparams");
                if (matchOus.Count() > 0)
                {
                    var ous = matchOus.First();
                    Params _params = ous.InterfaceParams;
                    ous.SpecialFlag = string.Empty;//复位
                    ous.InterfaceParams = null;//复位

                    //填充接口请求的设置
                    _sparams.tempFig_Day = _params.tempFig_Day.ConvertAll(x => (ushort)(x)).ToArray();
                    _sparams.tempFig_Target_Day = _params.tempFig_Target_Day.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.tempFig_Target_Night = _params.tempFig_Target_Night.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.tempFig_dTempMax = _params.tempFig_dTempMax.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.tempFig_WindMin = _params.tempFig_WindMin.ConvertAll(x => (uint)(x)).ToArray();
                    _sparams.tempFig_WindMax = _params.tempFig_WindMax.ConvertAll(x => (uint)(x)).ToArray();
                    _sparams.cool_Day = _params.cool_Day.ConvertAll(x => (ushort)(x)).ToArray();
                    _sparams.cool_STime = _params.cool_STime.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.cool_ETime = _params.cool_ETime.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.cool_STemp = _params.cool_STemp.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.cool_ETemp = _params.cool_ETemp.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.cool_EHumi = _params.cool_EHumi.ConvertAll(x => (ushort)(x * 10)).ToArray();

                    _sparams.cool_On = _params.cool_On.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.cool_Off = _params.cool_Off.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.heat_Day = _params.heat_Day.ConvertAll(x => (ushort)(x)).ToArray();
                    _sparams.heat_STime = _params.heat_STime.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.heat_ETime = _params.heat_ETime.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.heat_STemp = _params.heat_STemp.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.heat_ETemp = _params.heat_ETemp.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.heat_On = _params.heat_On.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.heat_Off = _params.heat_Off.ConvertAll(x => (ushort)(x * 10)).ToArray();
                    _sparams.heat_Percent = _params.heat_Percent.ConvertAll(x => (ushort)(x)).ToArray();
                    _sparams.timer_On = _params.timer_On.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.timer_Off = _params.timer_Off.ConvertAll(x => ushort.Parse(x.Replace(":", ""))).ToArray();
                    _sparams.alarm_TempSensor = _params.alarm_TempSensor.ConvertAll(x => (byte)(x)).ToArray();
                    _sparams.alarm_HumiSensor = _params.alarm_HumiSensor.ConvertAll(x => (byte)(x)).ToArray();

                    _sparams.sys_NH3CO2 = (byte)_params.sys_NH3CO2;
                    _sparams.addr_Wmeter = (byte)_params.addr_Wmeter;//2019-12-19 水表地址
                    _sparams.addr_Emeter = (byte)_params.addr_Emeter; //2019-12-19  电表地址
                    _sparams.sys_RunMode = (byte)_params.sys_RunMode;
                    _sparams.sys_TempMode = (byte)_params.sys_TempMode;
                    _sparams.sys_WindMode = (byte)_params.sys_WindMode;
                    _sparams.sys_DoorMode = (byte)_params.sys_DoorMode;
                    _sparams.sys_FanMin = (ushort)_params.sys_FanMin;
                    _sparams.sys_DoorMin = (ushort)_params.sys_DoorMin;
                    _sparams.sys_WindStep = (ushort)_params.sys_WindStep;
                    _sparams.sys_DoorStep = (ushort)_params.sys_DoorStep;
                    _sparams.sys_WindTime = (ushort)_params.sys_WindTime;
                    _sparams.sys_HumiAdd = (ushort)_params.sys_HumiAdd;
                    _sparams.sys_HumiHigh = (ushort)(_params.sys_HumiHigh * 10);
                    _sparams.sys_Humi_Delay = (ushort)(_params.sys_Humi_Delay * 10);
                    _sparams.sys_NH3Add = (ushort)_params.sys_NH3Add;
                    _sparams.sys_NH3High = (ushort)_params.sys_NH3High;
                    _sparams.sys_NH3_Delay = (ushort)(_params.sys_NH3_Delay * 10);
                    _sparams.sys_CO2Add = (ushort)_params.sys_CO2Add;
                    _sparams.sys_CO2High = (ushort)_params.sys_CO2High;
                    _sparams.sys_CO2_Delay = (ushort)(_params.sys_CO2_Delay * 10);
                    _sparams.sys_DayStart = ushort.Parse(_params.sys_DayStart.Replace(":", ""));
                    _sparams.sys_DayEnd = ushort.Parse(_params.sys_DayEnd.Replace(":", ""));
                    _sparams.alarm_DoorTO = (ushort)_params.alarm_DoorTO;
                    _sparams.alarm_TempMax = (ushort)(_params.alarm_TempMax * 10);
                    _sparams.alarm_TempMin = (ushort)(_params.alarm_TempMin * 10);
                    _sparams.alarm_TempDMax = (ushort)(_params.alarm_TempDMax * 10);
                    _sparams.alarm_TempDMin = (ushort)(_params.alarm_TempDMin * 10);
                    _sparams.alarm_HumiMax = (ushort)(_params.alarm_HumiMax * 10);
                    _sparams.alarm_HumiMin = (ushort)(_params.alarm_HumiMin * 10);
                    _sparams.alarm_CO2Max = (ushort)_params.alarm_CO2Max;
                    _sparams.alarm_NH3Max = (ushort)_params.alarm_NH3Max;
                    _sparams.alarm_WindMin = (uint)_params.alarm_WindMin;
                    _sparams.alarm_NH3Sensor = (byte)_params.alarm_NH3Sensor;
                    _sparams.alarm_CO2Sensor = (byte)_params.alarm_CO2Sensor;
                    _sparams.alarm_LostPower = (byte)_params.alarm_LostPower;
                    _sparams.sys_fixMaxWind = (uint)_params.sys_fixMaxWind;



                    byte[] buff = PacoToolKit.Memory.Common.StructToBytes(_sparams);
                    string data = PacoToolKit.Format.Formater.BytesToHexStr(buff);

                    info.DAddrReverse = info.DAddrReverse;
                    info.seqDec = 1;
                    info.C = "01";
                    info.AddrDec = 0;//从第0个字节开始读
                    info.DLenDec = data.Length / 2;
                    info.Data = data;

                    string msg = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                    Write(ous.session, msg);
                    var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                 where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                 select dt1;
                    if (matchs.Count() > 0)
                    {
                        var match = matchs.First();
                        match[4] = "写参数...";

                    }

                }
            }
            catch (Exception ex)
            {
                Invoke(new Action(() =>
                {
                    Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                    Log(ex.Message + " " + ex.StackTrace);
                }));
            }
        }

        private string EncodeParam()
        {
            string data = "";
            SParams _params = new SParams();

            var name = string.Empty;
            Control control = new Control();

            #region 温度曲线
            List<ushort> tempFig_Day = new List<ushort>();
            List<ushort> tempFig_Target_Day = new List<ushort>();
            List<ushort> tempFig_Target_Night = new List<ushort>();
            List<ushort> tempFig_dTempMax = new List<ushort>();
            List<UInt32> tempFig_WindMin = new List<UInt32>();
            List<UInt32> tempFig_WindMax = new List<UInt32>();

            for (int i = 0; i < 11; i++)
            {
                name = "tempFig_Day" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                tempFig_Day.Add(ushort.Parse(control.Text));

                name = "tempFig_Target_Day" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                tempFig_Target_Day.Add(ushort.Parse(control.Text));

                name = "tempFig_Target_Night" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                tempFig_Target_Night.Add(ushort.Parse(control.Text));

                name = "tempFig_dTempMax" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                tempFig_dTempMax.Add(ushort.Parse(control.Text));

                name = "tempFig_WindMin" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                tempFig_WindMin.Add(UInt32.Parse(control.Text));
                name = "tempFig_WindMax" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                tempFig_WindMax.Add(UInt32.Parse(control.Text));
            }
            _params.tempFig_Day = tempFig_Day.ToArray();
            _params.tempFig_Target_Day = tempFig_Target_Day.ToArray();

            _params.tempFig_Target_Night = tempFig_Target_Night.ToArray();
            _params.tempFig_dTempMax = tempFig_dTempMax.ToArray();
            _params.tempFig_WindMin = tempFig_WindMin.ToArray();
            _params.tempFig_WindMax = tempFig_WindMax.ToArray();
            #endregion

            #region 制冷--曲线
            List<ushort> cool_Day = new List<ushort>();
            List<ushort> cool_STime = new List<ushort>();
            List<ushort> cool_ETime = new List<ushort>();
            List<ushort> cool_STemp = new List<ushort>();
            List<ushort> cool_ETemp = new List<ushort>();
            List<ushort> cool_EHumi = new List<ushort>();
            List<ushort> cool_On = new List<ushort>();
            List<ushort> cool_Off = new List<ushort>();
            for (int i = 0; i < 11; i++)
            {
                name = "cool_Day" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_Day.Add(ushort.Parse(control.Text));


                name = "cool_STime" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_STime.Add(ushort.Parse(control.Text));


                name = "cool_ETime" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_ETime.Add(ushort.Parse(control.Text));


                name = "cool_STemp" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_STemp.Add(ushort.Parse(control.Text));


                name = "cool_ETemp" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_ETemp.Add(ushort.Parse(control.Text));


                name = "cool_EHumi" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_EHumi.Add(ushort.Parse(control.Text));


                name = "cool_On" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_On.Add(ushort.Parse(control.Text));



                name = "cool_Off" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];
                cool_Off.Add(ushort.Parse(control.Text));

            }
            _params.cool_Day = cool_Day.ToArray();
            _params.cool_STime = cool_STime.ToArray();
            _params.cool_ETime = cool_ETime.ToArray();
            _params.cool_STemp = cool_STemp.ToArray();
            _params.cool_ETemp = cool_ETemp.ToArray();
            _params.cool_EHumi = cool_EHumi.ToArray();
            _params.cool_On = cool_On.ToArray();
            _params.cool_Off = cool_Off.ToArray();
            #endregion

            #region 加热曲线
            List<ushort> heat_Day = new List<ushort>();
            List<ushort> heat_STime = new List<ushort>();
            List<ushort> heat_ETime = new List<ushort>();
            List<ushort> heat_STemp = new List<ushort>();
            List<ushort> heat_ETemp = new List<ushort>();
            List<ushort> heat_On = new List<ushort>();
            List<ushort> heat_Off = new List<ushort>();
            List<ushort> heat_Percent = new List<ushort>();

            for (int i = 0; i < 11; i++)
            {
                name = "heat_Day" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_Day.Add(ushort.Parse(control.Text));


                name = "heat_STime" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_STime.Add(ushort.Parse(control.Text));


                name = "heat_ETime" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_ETime.Add(ushort.Parse(control.Text));


                name = "heat_STemp" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_STemp.Add(ushort.Parse(control.Text));


                name = "heat_ETemp" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_ETemp.Add(ushort.Parse(control.Text));


                name = "heat_On" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_On.Add(ushort.Parse(control.Text));


                name = "heat_Off" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_Off.Add(ushort.Parse(control.Text));


                name = "heat_Percent" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                heat_Percent.Add(ushort.Parse(control.Text));

            }
            _params.heat_Day = heat_Day.ToArray();
            _params.heat_STime = heat_STime.ToArray();
            _params.heat_ETime = heat_ETime.ToArray();
            _params.heat_STemp = heat_STemp.ToArray();
            _params.heat_ETemp = heat_ETemp.ToArray();
            _params.heat_On = heat_On.ToArray();
            _params.heat_Off = heat_Off.ToArray();
            _params.heat_Percent = heat_Percent.ToArray();
            #endregion

            #region 定时输出
            List<ushort> timer_On = new List<ushort>();
            List<ushort> timer_Off = new List<ushort>();
            for (int i = 0; i < 5; i++)
            {
                name = "timer_On" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                timer_On.Add(ushort.Parse(control.Text));


                name = "timer_Off" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                timer_Off.Add(ushort.Parse(control.Text));

            }
            _params.timer_On = timer_On.ToArray();
            _params.timer_Off = timer_Off.ToArray();
            #endregion

            #region 校准
            List<short> cal_dTemp = new List<short>();
            for (int i = 0; i < 3; i++)
            {
                name = "cal_dTemp" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                cal_dTemp.Add(short.Parse(control.Text));

            }
            _params.cal_dTemp = cal_dTemp.ToArray();

            List<short> cal_dHumi = new List<short>();
            for (int i = 0; i < 1; i++)
            {
                name = "cal_dHumi" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                cal_dHumi.Add(short.Parse(control.Text));

            }
            _params.cal_dHumi = cal_dHumi.ToArray();

            name = "cal_dNH3";
            control = Controls.Find(name, true)[0];
            _params.cal_dNH3 = short.Parse(control.Text);

            name = "cal_dCO2";
            control = Controls.Find(name, true)[0];
            _params.cal_dCO2 = short.Parse(control.Text);

            name = "cal_Wind";
            control = Controls.Find(name, true)[0];
            _params.cal_Wind = UInt32.Parse(control.Text);

            name = "cal_Pulse";
            control = Controls.Find(name, true)[0];
            _params.cal_Pulse = UInt32.Parse(control.Text);
            #endregion

            #region 数量统计
            name = "mh_Day";
            control = Controls.Find(name, true)[0];
            _params.mh_Day = ushort.Parse(control.Text);

            name = "mh_PigNum";
            control = Controls.Find(name, true)[0];
            _params.mh_PigNum = ushort.Parse(control.Text);

            name = "mh_PerWind";
            control = Controls.Find(name, true)[0];
            _params.mh_PerWind = UInt32.Parse(control.Text);

            name = "sys_NH3CO2";
            control = Controls.Find(name, true)[0];
            _params.sys_NH3CO2 = (byte)(control as ComboBox).SelectedIndex;

            name = "addr_Wmeter";
            control = Controls.Find(name, true)[0];
            _params.addr_Wmeter = byte.Parse(control.Text);

            name = "addr_Emeter";
            control = Controls.Find(name, true)[0];
            _params.addr_Emeter = byte.Parse(control.Text);
            #endregion


            #region 模式控制
            name = "sys_RunMode";
            control = Controls.Find(name, true)[0];
            _params.sys_RunMode = (byte)(control as ComboBox).SelectedIndex;

            name = "sys_TempMode";
            control = Controls.Find(name, true)[0];
            _params.sys_TempMode = (byte)(control as ComboBox).SelectedIndex;

            name = "sys_WindMode";
            control = Controls.Find(name, true)[0];
            _params.sys_WindMode = (byte)(control as ComboBox).SelectedIndex;

            name = "sys_DoorMode";
            control = Controls.Find(name, true)[0];
            _params.sys_DoorMode = (byte)(control as ComboBox).SelectedIndex;
            #endregion

            #region 模式控制
            name = "sys_FanMin";
            control = Controls.Find(name, true)[0];
            _params.sys_FanMin = ushort.Parse(control.Text);

            name = "sys_DoorMin";
            control = Controls.Find(name, true)[0];
            _params.sys_DoorMin = ushort.Parse(control.Text);

            name = "sys_WindStep";
            control = Controls.Find(name, true)[0];
            _params.sys_WindStep = ushort.Parse(control.Text);

            name = "sys_DoorStep";
            control = Controls.Find(name, true)[0];
            _params.sys_DoorStep = ushort.Parse(control.Text);

            name = "sys_WindTime";
            control = Controls.Find(name, true)[0];
            _params.sys_WindTime = ushort.Parse(control.Text);

            name = "sys_HumiAdd";
            control = Controls.Find(name, true)[0];
            _params.sys_HumiAdd = ushort.Parse(control.Text);

            name = "sys_HumiHigh";
            control = Controls.Find(name, true)[0];
            _params.sys_HumiHigh = ushort.Parse(control.Text);

            name = "sys_Humi_Delay";
            control = Controls.Find(name, true)[0];
            _params.sys_Humi_Delay = ushort.Parse(control.Text);

            name = "sys_NH3Add";
            control = Controls.Find(name, true)[0];
            _params.sys_NH3Add = ushort.Parse(control.Text);

            name = "sys_NH3High";
            control = Controls.Find(name, true)[0];
            _params.sys_NH3High = ushort.Parse(control.Text);

            name = "sys_NH3_Delay";
            control = Controls.Find(name, true)[0];
            _params.sys_NH3_Delay = ushort.Parse(control.Text);

            name = "sys_CO2Add";
            control = Controls.Find(name, true)[0];
            _params.sys_CO2Add = ushort.Parse(control.Text);

            name = "sys_CO2High";
            control = Controls.Find(name, true)[0];
            _params.sys_CO2High = ushort.Parse(control.Text);

            name = "sys_CO2_Delay";
            control = Controls.Find(name, true)[0];
            _params.sys_CO2_Delay = ushort.Parse(control.Text);

            name = "sys_DayStart";
            control = Controls.Find(name, true)[0];
            _params.sys_DayStart = ushort.Parse(control.Text);

            name = "sys_DayEnd";
            control = Controls.Find(name, true)[0];
            _params.sys_DayEnd = ushort.Parse(control.Text);
            #endregion

            #region 报警参数
            name = "alarm_DoorTO";
            control = Controls.Find(name, true)[0];
            _params.alarm_DoorTO = ushort.Parse(control.Text);

            name = "alarm_TempMax";
            control = Controls.Find(name, true)[0];
            _params.alarm_TempMax = ushort.Parse(control.Text);

            name = "alarm_TempMin";
            control = Controls.Find(name, true)[0];
            _params.alarm_TempMin = ushort.Parse(control.Text);

            name = "alarm_TempDMax";
            control = Controls.Find(name, true)[0];
            _params.alarm_TempDMax = ushort.Parse(control.Text);

            name = "alarm_TempDMin";
            control = Controls.Find(name, true)[0];
            _params.alarm_TempDMin = ushort.Parse(control.Text);

            name = "alarm_HumiMax";
            control = Controls.Find(name, true)[0];
            _params.alarm_HumiMax = ushort.Parse(control.Text);

            name = "alarm_HumiMin";
            control = Controls.Find(name, true)[0];
            _params.alarm_HumiMin = ushort.Parse(control.Text);

            name = "alarm_CO2Max";
            control = Controls.Find(name, true)[0];
            _params.alarm_CO2Max = ushort.Parse(control.Text);

            name = "alarm_NH3Max";
            control = Controls.Find(name, true)[0];
            _params.alarm_NH3Max = ushort.Parse(control.Text);

            name = "alarm_WindMin";
            control = Controls.Find(name, true)[0];
            _params.alarm_WindMin = UInt32.Parse(control.Text);

            List<byte> alarm_TempSensor = new List<byte>();
            for (int i = 0; i < 3; i++)
            {
                name = "alarm_TempSensor" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                alarm_TempSensor.Add((byte)(control as ComboBox).SelectedIndex);

            }
            _params.alarm_TempSensor = alarm_TempSensor.ToArray();

            List<byte> alarm_HumiSensor = new List<byte>();
            for (int i = 0; i < 1; i++)
            {
                name = "alarm_HumiSensor" + (i + 1).ToString();
                control = Controls.Find(name, true)[0];

                alarm_HumiSensor.Add((byte)(control as ComboBox).SelectedIndex);

            }
            _params.alarm_HumiSensor = alarm_HumiSensor.ToArray();

            name = "alarm_NH3Sensor";
            control = Controls.Find(name, true)[0];
            _params.alarm_NH3Sensor = (byte)(control as ComboBox).SelectedIndex;

            name = "alarm_CO2Sensor";
            control = Controls.Find(name, true)[0];
            _params.alarm_CO2Sensor = (byte)(control as ComboBox).SelectedIndex;

            name = "alarm_LostPower";
            control = Controls.Find(name, true)[0];
            _params.alarm_LostPower = (byte)(control as ComboBox).SelectedIndex;

            name = "sys_fixMaxWind";
            control = Controls.Find(name, true)[0];
            _params.sys_fixMaxWind = UInt32.Parse(control.Text);
            #endregion

            #region 通讯设置
            name = "addr";
            control = Controls.Find(name, true)[0];
            _params.addr = UInt32.Parse(control.Text);

            name = "serverPort";
            control = Controls.Find(name, true)[0];
            _params.serverPort = ushort.Parse(control.Text);

            name = "serverIP";
            control = Controls.Find(name, true)[0];
            var block = control.Text.Split('.');
            var array = block.ToList().Select(x => byte.Parse(x)).ToArray();
            _params.serverIP = array;

            name = "localIP";
            control = Controls.Find(name, true)[0];
            block = control.Text.Split('.');
            array = block.ToList().Select(x => byte.Parse(x)).ToArray();
            _params.localIP = array;

            name = "gateway";
            control = Controls.Find(name, true)[0];
            block = control.Text.Split('.');
            array = block.ToList().Select(x => byte.Parse(x)).ToArray();
            _params.gateway = array;

            name = "netmask";
            control = Controls.Find(name, true)[0];
            block = control.Text.Split('.');
            array = block.ToList().Select(x => byte.Parse(x)).ToArray();
            _params.netmask = array;

            name = "comType";
            control = Controls.Find(name, true)[0];
            _params.comType = (byte)(control as ComboBox).SelectedIndex;
            #endregion

            byte[] buff = PacoToolKit.Memory.Common.StructToBytes(_params);
            data = PacoToolKit.Format.Formater.BytesToHexStr(buff);

            return data;
        }

        public void ReadStatus(string dAddrReverse)
        {
            try
            {
                var Ous = OUS_LIST.Where(x => x.DAddrReverse == dAddrReverse).ToList();
                if (Ous.Count == 0)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }
                else if (!Ous.First().session.Connected)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }

                var info = new OUServerProtocolRequestInfo();
                info.DAddrReverse = dAddrReverse;
                info.seqDec = 1;
                info.C = "02";
                info.AddrDec = 0;//从第0个字节开始读
                info.DLenDec = Marshal.SizeOf(typeof(SStatus));//读取60个字节
                info.Data = string.Empty;

                string msg = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                Write(Ous.First().session, msg);
                //this.statusStrip1.Items[0].Text = "读取...";
                var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                             where dt1.Field<string>("设备") == info.DAddrReverse //条件
                             select dt1;
                if (matchs.Count() > 0)
                {
                    var match = matchs.First();
                    match[4] = "读取状态...";

                }
            }
            catch (Exception ex)
            {
                Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                Log(ex.Message + " " + ex.StackTrace);
            }
        }

        private void ReadParams(string dAddrReverse)
        {
            try
            {
                var Ous = OUS_LIST.Where(x => x.DAddrReverse == dAddrReverse).ToList();
                if (Ous.Count == 0)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }
                else if (!Ous.First().session.Connected)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }

                var info = new OUServerProtocolRequestInfo();
                info.DAddrReverse = dAddrReverse;
                info.seqDec = 1;
                info.C = "00";
                info.AddrDec = 0;//从第0个字节开始读
                info.DLenDec = System.Runtime.InteropServices.Marshal.SizeOf(new SParams());//读取666个字节
                info.Data = string.Empty;

                string msg = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                Write(Ous.First().session, msg);
                //this.statusStrip1.Items[0].Text = "读取...";
                var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                             where dt1.Field<string>("设备") == info.DAddrReverse //条件
                             select dt1;
                if (matchs.Count() > 0)
                {
                    var match = matchs.First();
                    match[4] = "读取参数...";

                }
            }
            catch (Exception ex)
            {
                Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                Log(ex.Message + " " + ex.StackTrace);
            }
        }

        private void SetParams(string dAddrReverse)
        {
            try
            {
                var Ous = OUS_LIST.Where(x => x.DAddrReverse == dAddrReverse).ToList();
                if (Ous.Count == 0)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }
                else if (!Ous.First().session.Connected)
                {
                    Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                }

                string data = EncodeParam();

                var info = new OUServerProtocolRequestInfo();
                info.DAddrReverse = dAddrReverse;
                info.seqDec = 1;
                info.C = "01";
                info.AddrDec = 0;//从第0个字节开始读
                info.DLenDec = data.Length / 2;
                info.Data = data;

                string msg = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                Write(Ous.First().session, msg);
                var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                             where dt1.Field<string>("设备") == info.DAddrReverse //条件
                             select dt1;
                if (matchs.Count() > 0)
                {
                    var match = matchs.First();
                    match[4] = "写参数...";

                }
            }

            catch (Exception ex)
            {
                Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                Log(ex.Message + " " + ex.StackTrace);
            }
        }

        #region 固件相关
        public void ReadFirmware()
        {
            //加载固件
            if (Directory.Exists(FIRMWAREPATH) == false)//如果不存在就创建file文件夹
            {
                Directory.CreateDirectory(FIRMWAREPATH);
            }
            DirectoryInfo root = new DirectoryInfo(FIRMWAREPATH);
            FileInfo[] files = root.GetFiles();
            if (files.Count() > 0)
            {
                var file = files.First();
                Firmware.LocalFileName = file.Name;
                Firmware.LocalFileSize = (int)file.Length;
                Firmware.LocalTotalPart = (long)Math.Ceiling((decimal)file.Length / (decimal)firmware_single_size);
                Firmware.Content = PacoToolKit.File.Common.ReadFile(file.FullName);
                Firmware.LocalCrc16Hex = Formater.BytesToHexStr(Formater.crc16(Firmware.Content, (int)Firmware.LocalFileSize));

            }
            else
            {
                //Msg(FIRMWAREPATH+"未检测到有固件信息", ColorInfo, ColorText, 400, 1000);
                Logger.Info(FIRMWAREPATH + "未检测到有固件信息");
            }
        }

        #endregion

        #region 界面方法

        /// <summary>
        /// 判断二进制第几位是0/1
        /// </summary>
        /// <param name="targetNum">目标数</param>
        /// <param name="bitOffset">第几位(从0位开始)</param>
        /// <returns></returns>
        private long GetBitByOffset(uint targetNum, int bitOffset)
        {
            int temp = 1 << bitOffset;
            return (targetNum & temp) / temp;
        }

        private void checkAll(bool check)
        {
            bool current = Convert.ToBoolean(dataGridViewDeviceList.Rows[0].Cells[1].Value);
            //遍历datagridview中的每一行，判断是否选中，若为选中，则选中
            for (int i = 0; i < dataGridViewDeviceList.Rows.Count - 1; i++)
            {
                dataGridViewDeviceList.Rows[i].Cells[1].Value = (!current).ToString();
            }
        }

        public void PrintTimeJob()
        {
            TimeSpan runspan = DateTime.Now - GLOBAL_START_TIME;
            Invoke(new Action(() =>
            {
                statusStrip1.Text = string.Format("运行时间：{0}天 {1}时 {2}分 {3}秒", runspan.Days, runspan.Hours, runspan.Minutes, runspan.Seconds);
            }));
        }

        private string Space(string str)
        {
            return PacoToolKit.Format.Formater.AddSpace(str).ToUpper();
        }

        private void Msg(string lableText, Color backgroudColor, Color fontColor, int width = 400, int showTimeMiliSec = 1000)
        {
            if (this.IsHandleCreated)
            {
                BeginInvoke(new Action(() =>
                {
                    new FormToast(lableText, width, backgroudColor, fontColor, showTimeMiliSec).ShowDialog();
                }));
            }
        }
        public void Log(string msg)
        {
            /*
            if (this.IsHandleCreated)
            {
                BeginInvoke(new Action(() => {
                    Logger.Info(msg);
                    this.textBoxMessage.AppendText("[" + DateTime.Now.ToString() + "][*]: " + (msg) + "\n");
                }));
            }*/
            Logger.Info(msg);
        }
        private void LogR(string msg)
        {
            Logger.Info("[R]:" + msg);
            /*if (this.IsHandleCreated)
            {
                BeginInvoke(new Action(() => {
                    Logger.Info("[R]:" + msg);
                    this.textBoxMessage.AppendText("[" + DateTime.Now.ToString() + "][R]: " + (msg) + "\n");
                }));
            }*/
        }
        private void LogS(string msg)
        {
            Logger.Info("[S]:" + msg);
            /*if (this.IsHandleCreated)
            {
                BeginInvoke(new Action(() => {
                    Logger.Info("[S]:" + msg);
                    this.textBoxMessage.AppendText("[" + DateTime.Now.ToString() + "][S]: " + (msg) + "\n");
                }));
            }*/
        }
        public void Write(OUServerProtocolSession session, string msg)
        {
            try
            {
                byte[] buff = Formater.HexStringToBytesKeep(msg);
                session.Send(buff, 0, buff.Length);
                LogS(session.RemoteEndPoint.ToString() + "-> " + Space(msg));
            }
            catch
            {
                throw;
            }
        }
        public void Write2Web(ClientServerSession session, string msg)
        {
            try
            {
                session.Send(msg);
                LogS(session.RemoteEndPoint.ToString() + "-> " + (msg));
            }
            catch
            {
                throw;
            }
        }

        public void RestartSchedule(string name, IJob job)
        {
            //stop all
            JobManager.AllSchedules.Where(x => x.Name == name).ToList().ForEach(x =>
            {
                JobManager.RemoveJob(x.Name);
            });

            int timeInterval = (int)this.numericUpDownScheduleSpan.Value;
            if (timeInterval == 0)
            {
                Msg("间隔频率不能为0", Color.Tomato, Color.White, 400, 1000);
                return;
            }
            string type = this.comboBoxScheduleUnit.Text;

            switch (type)
            {
                case "秒":
                    JobManager.AddJob(job, s => s.WithName(name).NonReentrant().ToRunNow().AndEvery(timeInterval).Seconds());
                    break;
                case "分":
                    JobManager.AddJob(job, s => s.WithName(name).NonReentrant().ToRunNow().AndEvery(timeInterval).Minutes());
                    break;
                case "时":
                    JobManager.AddJob(job, s => s.WithName(name).NonReentrant().ToRunNow().AndEvery(timeInterval).Hours());
                    break;
                case "日":
                    JobManager.AddJob(job, s => s.WithName(name).NonReentrant().ToRunNow().AndEvery(timeInterval).Days());
                    break;
                case "周":
                    JobManager.AddJob(job, s => s.WithName("Test").NonReentrant().ToRunNow().AndEvery(timeInterval).Weeks());
                    break;
                case "月":
                    JobManager.AddJob(job, s => s.WithName("Test").NonReentrant().ToRunNow().AndEvery(timeInterval).Months());
                    break;
                default:
                    Msg("未识别类型", Color.Tomato, Color.White, 400, 1000);
                    return;
            }
            //Msg("任务已经重启", Color.DeepSkyBlue, Color.White, 400, 1000);
        }

        #endregion

        #region 界面事件
        private void toolStripButtonDebugMode_Click(object sender, EventArgs e)
        {
            if (this.tabPageDebug.Parent == null)
            {
                this.tabPageDebug.Parent = this.tabControl1;
                this.tabControl1.SelectedIndex = 3;
                DebugModel = DebugModel.Debug;
                Log("Enter Debug Model");
            }
            else
            {
                this.tabPageDebug.Parent = null;
                DebugModel = DebugModel.Release;
                Log("Exit Debug Model");
            }
        }
        private void toolStripButtonLog_Click(object sender, EventArgs e)
        {
            try
            {
                string path = APPPATH + "\\Logs";
                System.Diagnostics.Process.Start("explorer.exe", path);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        private void buttonCheckedAll_Click(object sender, EventArgs e)
        {
            checkAll(true);
        }
        private void dataGridViewDeviceList_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            #region 读取状态
            if (dataGridViewDeviceList.Columns[e.ColumnIndex].Name == "funBtn" && e.RowIndex >= 0)
            {
                //说明点击的列是DataGridViewButtonColumn列
                string check = dataGridViewDeviceList.CurrentRow.Cells[3].Value.ToString();
                string dAddrReverse = dataGridViewDeviceList.CurrentRow.Cells[4].Value.ToString();
                string remoteEndPoint = dataGridViewDeviceList.CurrentRow.Cells[5].Value.ToString();
                string action = dataGridViewDeviceList.CurrentRow.Cells[6].Value.ToString();
                //MessageBox.Show(check + " " + dAddrReverse + " " + remoteEndPoint + " " + action);
                ReadStatus(dAddrReverse);
            }
            #endregion
            #region 升级固件
            if (dataGridViewDeviceList.Columns[e.ColumnIndex].Name == "funBtn1" && e.RowIndex >= 0)
            {
                if (!CAN_UPDATE)
                {
                    new UnlockForm().ShowDialog();
                    if (CAN_UPDATE)
                    {

                    }
                    else
                    {
                        MessageBox.Show("操作已经取消");
                        return;
                    }
                }
                else
                {

                }

                string check = dataGridViewDeviceList.CurrentRow.Cells[3].Value.ToString();
                string dAddrReverse = dataGridViewDeviceList.CurrentRow.Cells[4].Value.ToString();
                string remoteEndPoint = dataGridViewDeviceList.CurrentRow.Cells[5].Value.ToString();
                string action = dataGridViewDeviceList.CurrentRow.Cells[6].Value.ToString();
                try
                {
                    var Ous = OUS_LIST.Where(x => x.DAddrReverse == dAddrReverse).ToList();
                    if (Ous.Count == 0)
                    {
                        Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                    }
                    else if (!Ous.First().session.Connected)
                    {
                        Msg("未选择设备或者设备不在线", Color.Tomato, Color.White, 400, 1000); return;
                    }

                    var info = new OUServerProtocolRequestInfo();
                    info.DAddrReverse = dAddrReverse;
                    info.seqDec = 1;
                    info.C = "30";
                    info.AddrDec = 0;//从第0个字节开始读
                    info.DLenDec = 42;//42
                    info.Data = string.Empty;

                    string msg = BaseEncoder.CreateMsg(info.DAddrReverse, info.seqDec, info.C, info.AddrDec, info.DLenDec, info.Data);
                    Write(Ous.First().session, msg);
                    //this.statusStrip1.Items[0].Text = "读取...";
                    var matchs = from dt1 in DeviceListDataTable.AsEnumerable()//查询
                                 where dt1.Field<string>("设备") == info.DAddrReverse //条件
                                 select dt1;
                    if (matchs.Count() > 0)
                    {
                        var match = matchs.First();
                        match[4] = "开始升级...";

                    }
                }
                catch (Exception ex)
                {
                    Msg(ex.Message, Color.Tomato, Color.White, 400, 1000);
                    Log(ex.Message + " " + ex.StackTrace);
                }
            }
            #endregion
            #region 读取参数
            if (dataGridViewDeviceList.Columns[e.ColumnIndex].Name == "funBtn2" && e.RowIndex >= 0)
            {
                string check = dataGridViewDeviceList.CurrentRow.Cells[3].Value.ToString();
                SELECTED_ADDR_REVERSE = dataGridViewDeviceList.CurrentRow.Cells[4].Value.ToString();
                labelSelectedAddr.Text = SELECTED_ADDR_REVERSE;
                string remoteEndPoint = dataGridViewDeviceList.CurrentRow.Cells[5].Value.ToString();
                string action = dataGridViewDeviceList.CurrentRow.Cells[6].Value.ToString();
                //ReadParams(SELECTED_ADDR_REVERSE);
                tabControl1.SelectedTab = this.tabPageParams;
            }
            #endregion
        }
        private void dataGridViewDeviceList_CellContentDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                var curRow = dataGridViewDeviceList.CurrentRow;
                string check = curRow.Cells[3].Value.ToString();
                SELECTED_ADDR_REVERSE = curRow.Cells[4].Value.ToString();
                labelSelectedAddr.Text = SELECTED_ADDR_REVERSE;
                string remoteEndPoint = curRow.Cells[5].Value.ToString();
                string action = curRow.Cells[6].Value.ToString();
                ReadParams(SELECTED_ADDR_REVERSE);
            }

        }

        private void buttonReadParams_Click(object sender, EventArgs e)
        {
            ReadParams(SELECTED_ADDR_REVERSE);
        }
        private void buttonApplyParams_Click(object sender, EventArgs e)
        {
            var controls = this.tabControlParams.Controls;

            foreach (TabPage page in controls)
            {
                foreach (Control c in page.Controls)
                {

                    if (c is TextBox)
                    {
                        if (!c.Name.Contains("_r"))
                        {
                            (c as TextBox).Text = (controls.Find(c.Name + "_r", true).First() as TextBox).Text;
                        }
                    }
                    if (c is ComboBox)
                    {
                        if (!c.Name.Contains("_r"))
                        {
                            (c as ComboBox).SelectedIndex = (controls.Find(c.Name + "_r", true).First() as ComboBox).SelectedIndex;
                        }
                    }
                }
            }


        }

        private void buttonSetParams_Click(object sender, EventArgs e)
        {
            SetParams(SELECTED_ADDR_REVERSE);
        }

        private void toolStripButtonExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void buttonGetCheckedRows_Click(object sender, EventArgs e)
        {
            List<string> checkedRowsIndex = new List<string>();
            foreach (DataRow row in DeviceListDataTable.Rows)
            {
                if (bool.Parse(row[0].ToString()))
                {
                    checkedRowsIndex.Add(row[1].ToString());
                }
            }
            MessageBox.Show(string.Join(",", checkedRowsIndex));
        }

        private void buttonClearInfo_Click(object sender, EventArgs e)
        {
            this.textBoxMessage.Clear();
        }

        private void buttonRestartSchedule_Click(object sender, EventArgs e)
        {
            RestartSchedule("Test", new TestJob(this));

        }

        private void buttonRunNow_Click(object sender, EventArgs e)
        {
            JobManager.AddJob(new RealTimeJob(this), s => s.WithName("RealTimeJob").NonReentrant().ToRunNow());
            Msg("任务已经执行", Color.DeepSkyBlue, Color.White, 400, 1000);
        }

        private void buttonStopAllSchedule_Click(object sender, EventArgs e)
        {
            //stop all
            JobManager.AllSchedules.ToList().ForEach(x =>
            {
                JobManager.RemoveJob(x.Name);
            });
            Msg("任务已经关闭", Color.Black, Color.White, 400, 1000);
        }

        private void buttonReadFirmware_Click(object sender, EventArgs e)
        {
            ReadFirmware();
            this.textBoxFirmwareInfo.Text = Firmware.LocalFileName;
            Msg("固件已经加载", ColorInfo, ColorText, 400, 1000);
        }





        #endregion

        private void textBox281_TextChanged(object sender, EventArgs e)
        {

        }

        private void buttonTest_Click(object sender, EventArgs e)
        {
            SParams p = new SParams();
            p.addr = 100;
            p.serverIP = new byte[4] { 192, 168, 1, 4 };
            p.localIP = new byte[4] { 192, 168, 1, 3 };
            p.gateway = new byte[4] { 192, 168, 1, 1 };
            p.netmask = new byte[4] { 255, 255, 255, 0 };
            p.comType = 1;
            byte[] buff = PacoToolKit.Memory.Common.StructToBytes(p);
            testbuff = PacoToolKit.Format.Formater.BytesToHexStr(buff);
            Log(testbuff);
        }

        private void buttonTest1_Click(object sender, EventArgs e)
        {
            SParams p = (SParams)PacoToolKit.Memory.Common.BytesToStruct(PacoToolKit.Format.Formater.HexStringToBytesKeep(testbuff), typeof(SParams), 23);
            Log(p.addr.ToString());
            Log(p.serverIP[0].ToString());
            Log(p.comType.ToString());

            var json = PacoToolKit.Json.Serializer.SerializeObject(p);
            Log(json);

            p = PacoToolKit.Json.Deserializer.DeserializeObject<SParams>(json);
            Log(p.addr.ToString());
            Log(p.serverIP[0].ToString());
            Log(p.comType.ToString());

        }



    }
}
